package com.um.jdy.platform.month.manager;

import cn.hutool.core.date.DateUtil;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.um.jdy.baofu.api.BaofuPayService;
import com.um.jdy.common.baofu.entity.po.BaofuRefund;
import com.um.jdy.common.baofu.service.BaofuRefundService;
import com.um.jdy.common.charge.code.OrderCode;
import com.um.jdy.common.charge.enums.OrderEnum;
import com.um.jdy.common.commons.manager.WxManager;
import com.um.jdy.common.commons.service.CommissionService;
import com.um.jdy.common.finance.entity.po.PlatformBill;
import com.um.jdy.common.finance.entity.po.UserBill;
import com.um.jdy.common.finance.enums.FinancialEnum;
import com.um.jdy.common.finance.service.MerchantBillService;
import com.um.jdy.common.finance.service.PlatformBillService;
import com.um.jdy.common.finance.service.UserBillService;
import com.um.jdy.common.member.enums.PayEnum;
import com.um.jdy.common.month.code.MonthCode;
import com.um.jdy.common.month.entity.po.CardOrder;
import com.um.jdy.common.month.entity.po.CardUser;
import com.um.jdy.common.month.service.CardUserService;
import com.um.jdy.platform.month.entity.dto.CardOrderRefundDTO;
import com.um.jdy.platform.month.entity.vo.CardOrderItemVO;
import com.um.jdy.platform.month.entity.vo.ExportCardOrderItemVO;
import com.um.springboot.starter.entity.Page;
import com.um.springboot.starter.exception.ServiceException;
import com.um.springboot.starter.orm.entity.Response;
import com.um.springboot.starter.orm.manager.BaseManager;
import com.um.jdy.common.month.service.CardOrderService;
import com.um.springboot.starter.orm.params.ExportParams;
import com.um.springboot.starter.orm.params.PageParams;
import com.um.springboot.starter.utils.*;
import com.um.weixin.pay.service.WxBasePayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 管理类：用户月卡订单
 */
@Component
public class CardOrderManager extends BaseManager<CardOrderService> {

    @Autowired
    WxManager wxManager;

    @Autowired
    WxBasePayService wxPayService;

    @Autowired
    CardUserService cardUserService;

    @Autowired
    UserBillService userBillService;

    @Autowired
    MerchantBillService merchantBillService;

    @Autowired
    PlatformBillService platformBillService;

    @Autowired
    CommissionService commissionService;
    @Autowired
    private BaofuPayService baofuPayService;

    @Autowired
    private BaofuRefundService baofuRefundService;

    /**
     * 分页查询订单
     * @param pageParams
     * @return
     */
    public Response<Page<CardOrderItemVO>> getPage(PageParams pageParams) {
        Page<CardOrderItemVO> page = new Page<>();
        page.setPageNo(pageParams.getPageNo());
        page.setPageSize(pageParams.getPageSize());

        pageParams.getCondition().put("o.com_id",getComId());

        page = service.getCMSViewModelPageBySqlName(page, "get_monthcard_order_page", "get_monthcard_order_count",
                CardOrderItemVO.class, pageParams.getProperties(), pageParams.getValues(),
                pageParams.getRangeEntitys(), pageParams.getOrderNames(), pageParams.getSortOns());
        return Response.success(page);
    }


    /**
     * 月卡退款
     *
     * @return
     */
    public Response refund(CardOrderRefundDTO dto) {
        CardOrder order = service.getEntity("order_no", dto.getOrderNo());
        if (order == null) {
            return Response.success(MonthCode.NoOrder);
        }

        if (StringUtil.equals(order.getPayStatus(), PayEnum.Status.UnPayed.name())) {
            return Response.success(OrderCode.UnPayNotSupportReturn);
        }

        String notifyUrl = "";
        if (dto.getAmount() + StringUtil.toInt(order.getReturnAmount()) > order.getPayAmount()) {
            return Response.failed("退款金额大于支付金额,当前已退款金额为：" + (order.getReturnAmount() / 100));
        }

        //逻辑判断：退款只能从最新的订单往之前的订单逐个退款
        //1、当前订单满足退款条件：仅需要判断是否有已升级的订单及上级订单是否已完全退款
        CardOrder lastOrder = service.getEntity(new String[]{"last_order_id","pay_status"},new Object[]{order.getMonthCardOrderId(),PayEnum.Status.Payed.name()});
        if(lastOrder != null && lastOrder.getReturnAmount() < lastOrder.getPayAmount()){
            return Response.failed("不支持退款,该订单有升级未退款订单："+lastOrder.getOrderNo());
        }

        String outTradeNo = order.getOutTradeNo();
        boolean refundSuccess = true;
        String returnMsg = "";

        if (!PayUtil.isDev()) {//非开发环境才退款
            if (order.getPayWay().equals(PayEnum.PayWay.Wxpay.name()) ) {
                /**try { todo 修改成宝付退款
                    wxManager.getPayService(order.getComId());
                    int toTotalFee = PayUtil.toTotalFee(order.getPayAmount());
                    wxPayService.refundOrder(outTradeNo, OrderUtil.getWxOrderNo(), toTotalFee, PayUtil.toTotalFee(dto.getAmount()));
                }catch (WxPayException ex){
                    returnMsg = ex.getCustomErrorMsg();
                    refundSuccess = false;
                }*/
                try {
                    //wxManager.getPayService(order.getComId());
                    String returnOutTradeNo = OrderUtil.getWxOrderNo();
                    String type ="monthCard";
                    int toTotalFee = PayUtil.toTotalFee(order.getPayAmount());
                    baofuPayService.refundOrder(outTradeNo,returnOutTradeNo,toTotalFee, PayUtil.toTotalFee(dto.getAmount()),type,order.getComId());
                    BaofuRefund baofuRefund = new BaofuRefund();
                    baofuRefund.setComId(order.getComId());
                    baofuRefund.setRefundAmount(PayUtil.toTotalFee(dto.getAmount()));
                    baofuRefund.setOutRefundNo(returnOutTradeNo);
                    baofuRefund.setRefundState("REFUND");
                    baofuRefund.setOutTradeNo(outTradeNo);
                    baofuRefund.setType(type);
                    baofuRefundService.addRefund(baofuRefund);
                    //todo 回调执行
                    refundSuccess = false;
                    return Response.success();
                }catch (ServiceException ex){
                    returnMsg = ex.getMsg();
                    refundSuccess = false;
                }
            }
        }

        if (refundSuccess) {
            //套餐降级
            CardOrder nextOrder = service.getEntity(order.getLastOrderId());
            if (nextOrder != null) {
                CardUser cardUser = cardUserService.getEntity(new String[]{"member_user_id","month_card_package_id"},new Object[]{order.getMemberUserId(),order.getMonthCardPackageId()});
                if(cardUser != null){
                    cardUser.setMonthCardPackageId(nextOrder.getMonthCardPackageId());
                    cardUser.setMaxPower(nextOrder.getMaxPower());
                    cardUserService.update(cardUser);
                }
            }else{//已经是最开始订单，则删除用户月卡
                CardUser cardUser = cardUserService.getEntity(new String[]{"member_user_id","month_card_package_id"},new Object[]{order.getMemberUserId(),order.getMonthCardPackageId()});
                if(cardUser != null)
                    cardUserService.delete(cardUser.getMonthCardUserId());
            }

            //退款金额
            int returnAmount = dto.getAmount();

            //月卡退回
            UserBill userBill = new UserBill();
            userBill.setMemberUserId(order.getMemberUserId());
            userBill.setNo(OrderUtil.getOrderNo());
            userBill.setOutTradeNo(outTradeNo);
            userBill.setOrderNo(order.getOrderNo());
            userBill.setAmount(returnAmount);
            userBill.setType(FinancialEnum.IncomeOrExpend.Income.name());//收入支出类型：0-收入，1-支出
            userBill.setEvent(FinancialEnum.UserBillEvent.MonthCardRefund.name());
            userBill.setStatus(FinancialEnum.BillStatus.Effective.name());//账单状态：0未生效|1已生效|2已失效
            userBill.setCreateTime(DateUtil.date());
            userBill.setRemark("后台管理员操作月卡退款");
            userBillService.save(userBill);

            //插入平台账单流水：充电退回
            PlatformBill platformBill = new PlatformBill();
            platformBill.setNo(OrderUtil.getOrderNo());
            platformBill.setOutTradeNo(outTradeNo);
            platformBill.setOrderNo(order.getOrderNo());
            platformBill.setAmount(returnAmount);
            platformBill.setType(FinancialEnum.IncomeOrExpend.Expend.name());//收入支出类型：0-收入，1-支出
            platformBill.setEvent(FinancialEnum.PlatformBillEvent.MonthCardRefund.name());
            platformBill.setStatus(FinancialEnum.BillStatus.Effective.name());//账单状态：0未生效|1已生效|2已失效
            platformBill.setCreateTime(DateUtil.date());
            platformBill.setRemark("后台管理员操作月卡退款");
            platformBillService.save(platformBill);

            int profit = commissionService.refundMonthCardCommission(order.getMonthCardOrderId(),order.getDeviceStationId(),new Date(),
                    order.getOrderNo(),order.getOutTradeNo(),returnAmount,order.getPayAmount());

            order.setReturnTime(new Date());
            order.setReturnStatus(OrderEnum.ReturnStatus.Success.name());
            order.setReturnAmount(order.getReturnAmount() + dto.getAmount());
            order.setProfit(profit);
            service.save(order);

            return Response.success();

        } else {
            return Response.failed("退款失败：" + returnMsg);
        }
    }


    public Response exportOrderPage(ExportParams exportParams) {
        exportParams.getCondition().put("o.com_id", getComId());
        List<ExportCardOrderItemVO> list = service.getCMSViewModelListBySqlName("get_monthcard_order_page", ExportCardOrderItemVO.class,exportParams.getProperties(),
                exportParams.getValues(),exportParams.getRangeEntitys(),exportParams.getOrderNames(),exportParams.getSortOns(),
                new Object[]{exportParams.getStart(),exportParams.getLimit()});


        list.stream().forEach(orderItem -> {
            orderItem.setStationAddress(orderItem.getProvince()+orderItem.getCity()+orderItem.getArea()+orderItem.getAddress());
        });

        Map mapFormat = new Hashtable();
        mapFormat.put("create_time","yyyy-MM-dd HH:mm:ss");
        mapFormat.put("pay_time","yyyy-MM-dd HH:mm:ss");
        mapFormat.put("start_date","yyyy-MM-dd");
        mapFormat.put("end_date","yyyy-MM-dd");

        mapFormat.put("pay_amount","number");
        mapFormat.put("return_amount","number");

        String fileName = "Excel"+ com.um.springboot.starter.utils.DateUtil.getDateString(new Date(), "yyyyMMddHHmmss")+".xls";
        String path = service.getExportFilePath(fileName);
        List<String> columns = Arrays.asList("订单编号","创建时间","商户订单号","用户昵称","用户手机","网点名称","网点地址","套餐名称","最大功率(瓦)",
               "支付金额","支付方式","支付状态","支付时间","退回金额","退款状态","月卡开始日期","月卡截止日期","订单备注");

        List<String> properties = Arrays.asList("order_no","create_time","out_trade_no","nickname","mobile","station_name","station_address","package_name","max_power",
                "pay_amount","pay_way","pay_status","pay_time","return_amount","return_status","start_date","end_date","remark");


        ExcelUtil.writeEntity(path, columns, list, properties, exportParams.getMapParam(), mapFormat, exportParams.getMapZero(),true);

        return Response.success(service.getDownFilePath(fileName));
    }

}
